using System;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace WpfApp1.Services
{
    /// <summary>
    /// TCP客户端包装类，实现短连接模式
    /// </summary>
    public class TcpClientWrapper : IDisposable
    {
        private TcpClient _tcpClient;
        private NetworkStream? _stream;
        private bool _disposed = false;

        public TcpClientWrapper()
        {
            _tcpClient = new TcpClient();
        }

        /// <summary>
        /// 连接到服务器
        /// </summary>
        /// <param name="serverIp">服务器IP地址</param>
        /// <param name="serverPort">服务器端口</param>
        /// <param name="timeoutMs">连接超时时间（毫秒）</param>
        public async Task ConnectAsync(string serverIp, int serverPort, int timeoutMs = 5000)
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(TcpClientWrapper));

            try
            {
                // 设置连接超时
                var connectTask = _tcpClient.ConnectAsync(serverIp, serverPort);
                var timeoutTask = Task.Delay(timeoutMs);

                var completedTask = await Task.WhenAny(connectTask, timeoutTask);
                if (completedTask == timeoutTask)
                {
                    throw new TimeoutException($"连接超时: {serverIp}:{serverPort}");
                }

                await connectTask; // 确保连接完成
                _stream = _tcpClient.GetStream();
            }
            catch (Exception)
            {
                Dispose();
                throw;
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data">要发送的数据</param>
        /// <param name="timeoutMs">发送超时时间（毫秒）</param>
        public async Task SendAsync(byte[] data, int timeoutMs = 5000)
        {
            if (_disposed || _stream == null)
                throw new InvalidOperationException("客户端未连接或已释放");

            try
            {
                _stream.WriteTimeout = timeoutMs;
                await _stream.WriteAsync(data, 0, data.Length);
                await _stream.FlushAsync();
            }
            catch (Exception)
            {
                Dispose();
                throw;
            }
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="bufferSize">接收缓冲区大小</param>
        /// <param name="timeoutMs">接收超时时间（毫秒）</param>
        /// <returns>接收到的数据</returns>
        public async Task<byte[]> ReceiveAsync(int bufferSize = 1024, int timeoutMs = 5000)
        {
            if (_disposed || _stream == null)
                throw new InvalidOperationException("客户端未连接或已释放");

            try
            {
                _stream.ReadTimeout = timeoutMs;
                byte[] buffer = new byte[bufferSize];
                int bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length);

                if (bytesRead == 0)
                    return new byte[0];

                byte[] result = new byte[bytesRead];
                Array.Copy(buffer, result, bytesRead);
                return result;
            }
            catch (Exception)
            {
                Dispose();
                throw;
            }
        }

        /// <summary>
        /// 发送命令并接收响应
        /// </summary>
        /// <param name="command">要发送的命令</param>
        /// <param name="timeoutMs">超时时间（毫秒）</param>
        /// <returns>服务器响应</returns>
        public async Task<byte[]> SendCommandAsync(string command, int timeoutMs = 5000)
        {
            byte[] cmdData = CreateCmdData(command);
            await SendAsync(cmdData, timeoutMs);
            return await ReceiveAsync(1024, timeoutMs);
        }

        /// <summary>
        /// 创建命令数据包
        /// </summary>
        /// <param name="cmd">命令字符串</param>
        /// <returns>命令数据包</returns>
        public static byte[] CreateCmdData(string cmd)
        {
            // 构建报文：STX + 数据 + ETX
            byte[] packet = new byte[cmd.Length + 2];
            packet[0] = 0x02; // STX
            System.Text.Encoding.ASCII.GetBytes(cmd).CopyTo(packet, 1);
            packet[packet.Length - 1] = 0x03; // ETX

            return packet;
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        public void Close()
        {
            Dispose();
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                _stream?.Close();
                _stream?.Dispose();
                _tcpClient?.Close();
                _tcpClient?.Dispose();
                _disposed = true;
            }
        }
    }
}
